<route lang="json5" type="page">
{
  style: {
    navigationBarTitleText: '播放历史',
    navigationStyle: 'default',
  },
  needLogin: 'true',
}
</route>

<template>
  <wd-toast />
  <wd-message-box />

  <view class="container">
    <!-- 添加遮罩层，当音频播放器显示时覆盖整个列表区域 -->
    <view
      v-if="isPlaying && playingItem.mediaType === 'audio'"
      class="mask-layer"
      @touchmove.prevent
    ></view>
    <!-- 顶部操作栏 -->
    <view class="action-bar" v-if="historyList.length > 0">
      <wd-checkbox
        label="all"
        v-model="isAllSelected"
        :indeterminate="isIndeterminate"
        @change="handleSelectionChange"
      >
        全选
      </wd-checkbox>

      <view class="action-buttons">
        <wd-button
          v-if="selectedMediaIds.length > 0"
          size="small"
          type="error"
          plain
          @click="openDeleteDialog"
        >
          <wd-icon name="delete" size="16px" />
          删除选中
        </wd-button>
        <wd-button size="small" type="error" plain @click="openClearAllDialog">
          <wd-icon name="delete" size="16px" />
          清空全部
        </wd-button>
      </view>
    </view>

    <!-- 空状态提示 -->
    <view v-if="!loading && historyList.length === 0" class="empty-state">
      <wd-img
        src=""
        width="300rpx"
        height="300rpx"
        mode="aspectFit"
      />
      <text class="empty-text">暂无播放历史</text>
      <text class="empty-subtext">快去发现更多精彩内容吧～</text>
      <view class="discover-btn">
        <wd-button type="warning" size="medium" @click="goDiscover">
          <wd-icon name="view" color="#fff" />
          去发现
        </wd-button>
      </view>
    </view>

    <!-- 历史记录列表 -->
    <u-scroll-view v-else scroll-y class="list-container">
      <view
        v-for="(item, index) in historyList"
        :key="index"
        class="list-item"
        :class="item.mediaType"
        :style="{ '--index': index }"
      >
        <view class="selection-box">
          <wd-checkbox-group v-model="selectedMediaIds">
            <wd-checkbox :modelValue="item.mediaId" />
          </wd-checkbox-group>
        </view>

        <view class="item-content" @click="playHistoryItem(item)">
          <text class="title">{{ item.title }}</text>

          <view class="meta-container">
            <text class="meta-item album">
              {{ item.albumName }}
            </text>
            <text class="meta-item category">
              {{ item.categoryName }}
            </text>
            <text class="meta-item time">
              <wd-icon name="clock" size="16px" color="#ff6b6b" />
              {{ formatDate(item.startTime) }}
            </text>
          </view>

          <view class="progress-container">
            <view class="progress-bar">
              <view
                class="progress-fill"
                :style="{ width: `${(item.progressSeconds / item.durationSeconds) * 100}%` }"
              />
            </view>
            <text class="progress-text">
              {{ videoPlayer.formatTime(item.progressSeconds) }} /
              {{ videoPlayer.formatTime(item.durationSeconds) }}
            </text>
          </view>
        </view>
      </view>
    </u-scroll-view>

    <!-- 视频播放器弹窗 -->
    <video-player-popup
      v-model:showVideoPlayer="showVideoPlayer"
      :item="playingItem"
      :loading-prev="loadingPrev"
      :loading-next="loadingNext"
      @end="handleVideoEnded"
      @show-playlist="handleShowPlaylist"
      @prev="playPrevMedia"
      @next="playNextMedia"
    />

    <!-- 播放列表弹窗 -->
    <play-list-popup
      v-model:showPlaylist="showPlaylist"
      :data="playlistData"
      :tabs="playlistTabs"
      :current-page="currentTabPage"
      :playing-item="playingItem"
      :loading="playlistLoading"
      :format-duration="formatTime"
      @play="playFromList"
      @switch-page="switchTabPage"
      @update:show="(val) => (showPlaylist = val)"
    />

    <!-- 固定底部的音频播放器 -->
    <audio-player-bar
      :show="playingItem && playingItem.mediaType === 'audio'"
      :playing-item="playingItem"
      :is-playing="isPlaying"
      v-model:sliderValue="sliderValue"
      :format-time="formatTime"
      @prev="playPrevMedia"
      @next="playNextMedia"
      @toggle="toggleAudio(playingItem)"
      @stop="stopAudio"
      @seek="handleAudioSeekChange"
    />

    <!-- 分页控件（非空时显示） -->
    <view v-if="historyList.length > 0 && !isPlaying" class="pagination-container">
      <wd-pagination
        v-model="currentPage"
        :page-size="pageSize"
        :total="total"
        @change="handlePageChange"
        show-icon
      />
    </view>
  </view>
</template>

<script lang="ts" setup>
import { ref, onMounted, computed, watch } from 'vue'
import { http } from '@/utils/http'
import { useToast, useMessage } from 'wot-design-uni'
import { useAuthHeaders, getCurrentUserId } from '@/utils/token'
import type { PlaybackHistoryView, MediaView } from '@/api/children.typing'
import { PageResult } from '@/api/poem.typings'
import dayjs from 'dayjs'
import isYesterday from 'dayjs/plugin/isYesterday'
import isToday from 'dayjs/plugin/isToday'
import localizedFormat from 'dayjs/plugin/localizedFormat'

import videoPlayerPopup from '@/components/video-player-popup/video-player-popup.vue'
import playListPopup from '@/components/play-list-popup/play-list-popup.vue'
import audioPlayerBar from '@/components/audio-player-bar/audio-player-bar.vue'
import { useMediaPlayer } from '@/utils/media/useMediaPlayer'

// 启用插件
dayjs.extend(isToday)
dayjs.extend(isYesterday)
dayjs.extend(localizedFormat)
dayjs.locale('zh-cn')

const {
  playingItem,
  isPlaying,
  sliderValue,
  showVideoPlayer,
  toggleAudio,
  stopAudio,
  handleMediaPlay,
  closeVideoPlayer,
  formatTime,
  checkMediaExpiration,
  handleAudioSeekChange,
  audioPlayer,
  videoPlayer,
  calculateTabForCurrentItem,
  playFromList,
  playlistLoading,
  loadingNext,
  loadingPrev,
  playlistTabs,
  currentTabPage,
  showPlaylist,
  lastPlaylistTab,
  ITEMS_PER_TAB,
  playlistData,
  playNextMedia: _playNextMedia,
  playPrevMedia: _playPrevMedia,
} = useMediaPlayer()

const toast = useToast()
const message = useMessage()
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL

// 历史记录数据
const historyList = ref<PlaybackHistoryView[]>([])
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
const loading = ref(false) // 初始加载状态
const loadingMediaPage = ref(false)

// 播放器弹窗相关
const activeTabId = ref('')

// 删除功能相关状态
const selectedMediaIds = ref<number[]>([])
const isIndeterminate = ref(false) // 全选状态：true-部分选中，false-未全选

// 计算属性：是否已全选
const isAllSelected = ref(false)

// 监听单选变化，更新全选状态
watch(selectedMediaIds, (newVal) => {
  const totalItems = historyList.value.length
  const selectedCount = newVal.length

  // 更新全选状态
  isAllSelected.value = selectedCount === totalItems && totalItems > 0
  isIndeterminate.value = selectedCount > 0 && selectedCount < totalItems
})

onMounted(() => {
  fetchHistoryList()
})

const fetchHistoryList = async () => {
  if (loading.value) return
  loading.value = true

  try {
    const requestParams = {
      pageNum: currentPage.value,
      pageSize: pageSize.value,
      userId: getCurrentUserId(),
    }
    const res = await http.get<PageResult<PlaybackHistoryView>>(
      `${API_BASE_URL}/api/v1/playback_history/page`,
      requestParams,
      useAuthHeaders(),
    )

    if (res.code === 200) {
      historyList.value = res.data.list
      total.value = res.data.total
      // 重置选择状态
      selectedMediaIds.value = []
    } else {
      console.error(`加载历史记录失败: ${res.msg}`)
      toast.error(`加载历史记录失败: ${res.msg}`)
    }
  } catch (error) {
    toast.error(`加载历史记录失败: ${error}`)
  } finally {
    loading.value = false
  }
}

/**
 * 获取当前媒体文件所在的页数据失败
 */
const getMediaPageById = async () => {
  if (loadingMediaPage.value) return
  loadingMediaPage.value = true

  try {
    const requestParams = {
      mediaId: playingItem.value.id,
      pageSize: pageSize.value,
      userId: getCurrentUserId(),
    }
    const res = await http.get<PageResult<PlaybackHistoryView>>(
      `${API_BASE_URL}/api/v1/media/position`,
      requestParams,
      useAuthHeaders(),
    )

    if (res.code === 200) {
      playlistData.value.list = res.data.list
      playlistData.value.total = res.data.total
      playlistData.value.pageNum = res.data.pageNum
    } else {
      toast.error(`获取当前媒体文件所在的页数据失败: ${res.msg}`)
    }
  } catch (error) {
    toast.error(`获取当前媒体文件所在的页数据失败: ${error}`)
  } finally {
    loadingMediaPage.value = false
  }
}

// 打开播放列表弹窗
const handleShowPlaylist = async () => {
  await getMediaPageById()
  activeTabId.value = `tab-${playlistData.value.pageNum - 1}`
  showPlaylist.value = true
  // 如果已经有播放项，自动跳转到对应的标签页
  if (playingItem.value) {
    currentTabPage.value = calculateTabForCurrentItem()
  } else {
    // 使用上次访问的标签页
    currentTabPage.value = lastPlaylistTab.value
  }
}

// 切换标签页
const switchTabPage = (index: number) => {
  currentTabPage.value = index
  lastPlaylistTab.value = index
  activeTabId.value = `tab-${index}`
  console.log(activeTabId.value)
  getMediaPageById()
}

// 处理全选/取消全选
const handleSelectionChange = (checked: boolean) => {
  if (checked) {
    // 全选
    selectedMediaIds.value = historyList.value.map((item) => item.mediaId)
    isIndeterminate.value = false
  } else {
    // 取消全选
    selectedMediaIds.value = []
    isIndeterminate.value = false
  }
}

// 打开删除对话框
const openDeleteDialog = () => {
  if (selectedMediaIds.value.length === 0) {
    toast.warning('请先选择要删除的历史记录')
    return
  }
  message
    .confirm({
      msg: '确定要删除选中的历史记录吗？',
      title: '确认删除',
    })
    .then(() => {
      confirmDelete()
    })
    .catch(() => {})
}

// 确认删除选中项
const confirmDelete = async () => {
  try {
    const params = {
      mediaIdList: selectedMediaIds.value,
      clearAll: false,
      userId: getCurrentUserId(),
    }

    const res = await http.post(
      `${API_BASE_URL}/api/v1/playback_history/clear`,
      params,
      {},
      useAuthHeaders(),
    )

    if (res.code === 200) {
      toast.show('删除成功')
      // 刷新列表
      await fetchHistoryList()
    } else {
      console.error(`删除失败: ${res.msg}`)
      toast.error(`删除失败: ${res.msg}`)
    }
  } catch (error) {
    toast.error(`删除失败: ${error}`)
  } finally {
  }
}

// 打开清空全部对话框
const openClearAllDialog = () => {
  message
    .confirm({
      msg: '确定要清空全部播放历史吗？',
      title: '确认清空',
    })
    .then(() => {
      confirmClearAll()
    })
    .catch(() => {})
}

// 确认清空全部
const confirmClearAll = async () => {
  try {
    const params = {
      clearAll: true,
      userId: getCurrentUserId(),
    }

    const res = await http.post(
      `${API_BASE_URL}/api/v1/playback_history/clear`,
      params,
      {},
      useAuthHeaders(),
    )

    if (res.code === 200) {
      toast.success('已清空全部播放历史')
      // 刷新列表
      await fetchHistoryList()
    } else {
      console.error(`清空失败: ${res.msg}`)
      toast.error(`清空失败: ${res.msg}`)
    }
  } catch (error) {
    toast.error(`清空失败: ${error}`)
  } finally {
  }
}

const handleVideoEnded = () => {
  if (playingItem.value) {
    videoPlayer.savePlaybackProgress(playingItem.value.id, videoPlayer.duration.value)
  }
  toast.show({ msg: '播放结束，自动播放下一首', duration: 1000 })
  playNextMedia()
}

const handlePageChange = (page: number) => {
  currentPage.value = page
  fetchHistoryList()
}

const formatDate = (dateString: string) => {
  // 解决 iOS 兼容性问题
  const date = dayjs(dateString.replace(' ', 'T') + '+08:00')

  if (date.isToday()) {
    return `今天 ${date.format('HH:mm')}`
  }

  if (date.isYesterday()) {
    return `昨天 ${date.format('HH:mm')}`
  }

  return date.format('YYYY年MM月DD日')
}

const playHistoryItem = async (item: PlaybackHistoryView) => {
  // 获取媒体详情
  const mediaDetail = await fetchMediaDetail(item.mediaId)

  if (!mediaDetail) {
    toast.error('获取媒体详情失败')
    return
  }

  handleMediaPlay(mediaDetail)
  // 获取媒体文件所在的页数据
  await getMediaPageById()
}

const fetchMediaDetail = async (mediaId: number) => {
  try {
    const res = await http.get<MediaView>(
      `${API_BASE_URL}/api/v1/media/${mediaId}`,
      {},
      useAuthHeaders(),
    )

    if (res.code === 200) {
      return res.data
    }
    return null
  } catch (error) {
    console.error('获取媒体详情失败', error)
    return null
  }
}

const goDiscover = () => {
  uni.switchTab({ url: '/pages/poem/children/index' })
}

const playNextMedia = () => {
  _playNextMedia(playlistData.value.list)
}

const playPrevMedia = () => {
  _playPrevMedia(playlistData.value.list)
}
</script>

<style scoped lang="scss">
.container {
  background-color: #f8fafc;
  padding: 20rpx;
  height: 100vh;
}

/* 遮罩层样式 */
.mask-layer {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 100rpx; /* 确保播放器区域不被覆盖 */
  z-index: 90;
  background: rgba(0, 0, 0, 0.01); /* 几乎透明的背景 */
  pointer-eve: auto;
}

.action-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20rpx 24rpx;
  background-color: #fff;
  border-radius: 16rpx;
  margin-bottom: 24rpx;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);

  .action-buttons {
    display: flex;
    gap: 20rpx;

    :deep(.wd-button) {
      padding: 0 24rpx;
      height: 60rpx;
      font-size: 28rpx;

      .wd-icon {
        margin-right: 8rpx;
      }
    }
  }
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 80vh;
  text-align: center;

  .empty-text {
    font-size: 36rpx;
    font-weight: 600;
    color: #334155;
    margin-top: 20rpx;
  }

  .empty-subtext {
    font-size: 28rpx;
    color: #94a3b8;
    margin-top: 12rpx;
  }

  .discover-btn {
    display: flex;
    margin-top: 20rpx;
  }
}

.list-container {
  height: calc(100vh - 200rpx);

  .list-item {
    position: relative;
    display: flex;
    padding: 32rpx;
    margin-bottom: 24rpx;
    border-radius: 24rpx;
    background-color: #fff;
    box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
    transition: all 0.3s ease;
    overflow: hidden;

    .selection-box {
      display: flex;
      align-items: center;
      margin-right: 24rpx;
      z-index: 2;
    }

    // 音频项背景
    &.audio {
      background: linear-gradient(
        135deg,
        rgba(91, 142, 255, 0.08) 0%,
        rgba(255, 255, 255, 0.95) 100%
      );

      &:before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 8rpx;
        height: 100%;
        background: linear-gradient(to bottom, #5b8eff, #3b7cff);
      }

      .media-badge {
        background: linear-gradient(135deg, #5b8eff, #3b7cff);
      }
    }

    // 视频项背景
    &.video {
      background: linear-gradient(
        135deg,
        rgba(0, 196, 140, 0.08) 0%,
        rgba(255, 255, 255, 0.95) 100%
      );

      &:before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 8rpx;
        height: 100%;
        background: linear-gradient(to bottom, #00c48c, #00a67c);
      }

      .media-badge {
        background: linear-gradient(135deg, #00c48c, #00a67c);
      }
    }

    // 点击效果
    &:active {
      transform: translateY(-4rpx);
      box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.1);
    }
  }
}

.media-badge {
  width: 64rpx;
  height: 64rpx;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 24rpx;
  flex-shrink: 0;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}

.item-content {
  flex: 1;
}

.title {
  font-size: 34rpx;
  font-weight: 600;
  color: #1e293b;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;

  .audio & {
    color: #2563eb;
  }

  .video & {
    color: #0d9488;
  }
}

.meta-container {
  display: flex;
  flex-wrap: wrap;
  gap: 20rpx;
  margin: 16rpx 0;
}

.meta-item {
  display: inline-flex;
  align-items: center;
  font-size: 26rpx;
  padding: 6rpx 16rpx;
  border-radius: 40rpx;
  background-color: rgba(241, 245, 249, 0.5);

  &.album {
    color: #2563eb;
  }

  &.category {
    color: #0d9488;
  }

  &.time {
    color: #dc2626;
  }

  :deep(.wd-icon) {
    margin-right: 8rpx;
  }
}

.progress-container {
  display: flex;
  align-items: center;
  gap: 20rpx;
  margin-top: 16rpx;

  .progress-bar {
    flex: 1;
    height: 10rpx;
    background-color: #e2e8f0;
    border-radius: 10rpx;
    overflow: hidden;

    .progress-fill {
      height: 100%;
      border-radius: 10rpx;
      transition: width 0.3s ease;

      .audio & {
        background: linear-gradient(90deg, #3b82f6, #60a5fa);
      }

      .video & {
        background: linear-gradient(90deg, #10b981, #34d399);
      }
    }
  }

  .progress-text {
    font-size: 24rpx;
    color: #64748b;
    min-width: 180rpx;
    text-align: right;
    font-weight: 500;

    .audio & {
      color: #3b82f6;
    }

    .video & {
      color: #10b981;
    }
  }
}

.pagination-container {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: #fff;
  padding: 20rpx;
  box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
  z-index: 100;
}

/* 动画效果 */
@keyframes itemEntrance {
  from {
    opacity: 0;
    transform: translateY(20rpx);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.list-item {
  animation: itemEntrance 0.4s ease forwards;
  animation-delay: calc(var(--index) * 0.08s);
  opacity: 0;
}

::-webkit-scrollbar {
  width: 0;
  background: transparent;
}
</style>
